package com.lsh.payment.core.service.allinpay.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.payment.api.model.allinpay.AllinCodeContent;
import com.lsh.payment.api.model.allinpay.AllinResponse;
import com.lsh.payment.api.model.basevo.BaseResponse;
import com.lsh.payment.api.model.basevo.ExceptionStatus;
import com.lsh.payment.api.model.payment.PaymentRequest;
import com.lsh.payment.api.model.qfpay.QfPayContent;
import com.lsh.payment.api.model.qfpay.QfResponse;
import com.lsh.payment.core.constant.BusinessConstant;
import com.lsh.payment.core.exception.BusinessException;
import com.lsh.payment.core.model.payasync.payTaskModel;
import com.lsh.payment.core.model.payenum.PayStatus;
import com.lsh.payment.core.model.payenum.PayWay;
import com.lsh.payment.core.model.payment.PayDeal;
import com.lsh.payment.core.service.async.PayEventBus;
import com.lsh.payment.core.service.payment.IPayChannelService;
import com.lsh.payment.core.service.payment.impl.PayBaseService;
import com.lsh.payment.core.service.payment.impl.PayDealService;
import com.lsh.payment.core.strategy.config.AllinPayConfig;
import com.lsh.payment.core.strategy.payment.PayStrategyContext;
import com.lsh.payment.core.strategy.vo.allinpay.AllinpayResponse;
import com.lsh.payment.core.util.PayAssert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * Project Name: lsh-payment
 * Created by miaozhuang
 * Date: 17/8/23
 * 北京链商电子商务有限公司
 * Package com.lsh.payment.core.service.xypay.impl
 * desc:
 */
@Service
public class AllinPayServiceImpl implements IPayChannelService {

    private static Logger logger = LoggerFactory.getLogger(AllinPayServiceImpl.class);

    @Autowired
    private PayBaseService payBaseService;

    @Autowired
    private PayDealService payDealService;

    @Resource
    private PayStrategyContext strategies;

    @Override
//    @Transactional(rollbackFor = Exception.class)
    public BaseResponse prepay(PaymentRequest paymentRequest) {

        //字段校验
        PayAssert.notNull(paymentRequest.getTrade_module(), ExceptionStatus.E1002002.getCode(), ExceptionStatus.E1002002.getMessage());
        if (!paymentRequest.getPay_way().equals(PayWay.ANDROID.getName()) && !paymentRequest.getPay_way().equals(PayWay.WINDOWS.getName())) {
            throw new BusinessException(ExceptionStatus.E1002002.getCode(), "payWay 字段错误");
        }

        QfResponse<QfPayContent> response = new QfResponse<>();
        QfPayContent content = this.DealPayAllinRequest(paymentRequest);
        response.setContent(content);
        response.setRet(Integer.parseInt(ExceptionStatus.SUCCESS.getCode()));
        response.setMsg(ExceptionStatus.SUCCESS.getMessage());
        return response;

    }

    /**
     * @param paymentRequest 通联请求参数
     * @return QfResponse     通联返回参数
     */
    private QfPayContent DealPayAllinRequest(PaymentRequest paymentRequest) {
        QfPayContent respContent = new QfPayContent();
        //入库
        PayDeal payDeal = payBaseService.prePayment(paymentRequest);

        //填写返回参数
        respContent.setTitle(MessageFormat.format(AllinPayConfig.ALLIN_PAY_TITLE, payDeal.getTradeId()));
        respContent.setAuthedAmount(payDeal.getRequestAmount().toString());
        respContent.setTrade_id(payDeal.getTradeId());
        respContent.setPayPaymentNo(payDeal.getPayPaymentNo());
        respContent.setChannelName(payDeal.getPayChannel());
        respContent.setPayStatus(1);

        //已经成功直接返回
        if (PayStatus.PAY_SUCCESS.getValue() == payDeal.getPayStatus()) {
            respContent.setHaspayed("true");//已经支付成功
            return respContent;
        }

        //调用第三方进行支付
        String qfPayResult = this.requestAllinChannel(payDeal, paymentRequest);
        respContent.setHaspayed("false");

        respContent.setResult(JSON.parseObject((qfPayResult)));

        //记录操作日志
//        payLogService.insertLog(payDeal.getPayId(), payDeal.getPayPaymentNo(), payDeal.getTradeId(), PayStatus.CREATE_PAYMENT.getValue(), BusiConstant.OPERATE_SUCCESS, JSON.toJSONString(paymentRequest), JSON.toJSONString(respContent));

        return respContent;
    }

    /**
     * @param paymentRequest 通联请求参数
     * @return QfResponse     通联返回参数
     */
    private AllinCodeContent DealPayAllinCodeRequest(PaymentRequest paymentRequest) {
        AllinCodeContent respContent = new AllinCodeContent();
        //入库
        PayDeal payDeal = payBaseService.prePayment(paymentRequest);

        //填写返回参数
        respContent.setTitle(MessageFormat.format(AllinPayConfig.ALLIN_PAY_TITLE, payDeal.getTradeId()));
        respContent.setAuthedAmount(payDeal.getRequestAmount().toString());
        respContent.setTradeId(payDeal.getTradeId());
        respContent.setPayPaymentNo(payDeal.getPayPaymentNo());
        respContent.setChannelName(payDeal.getPayChannel());
        respContent.setPayChannel(payDeal.getTradeType() + "");
        respContent.setPayStatus(1);

        //已经成功直接返回
        if (PayStatus.PAY_SUCCESS.getValue() == payDeal.getPayStatus()) {
//            respContent.setHaspayed("true");//已经支付成功
            return respContent;
        }

        //调用第三方进行支付
        AllinpayResponse allinpayResponse = this.requestAllinCodeChannel(payDeal, paymentRequest);

        if (allinpayResponse != null) {
            JSONObject coderSesult = JSON.parseObject(allinpayResponse.getMsg());

            respContent.setResult(coderSesult.toJSONString());
            respContent.setAcct_id(allinpayResponse.getAcct());
            //TODO 优化
            respContent.setPayStatus(Integer.parseInt(allinpayResponse.getCode()));
        } else {

            respContent.setPayStatus(Integer.parseInt(BusinessConstant.PAY_REQUEST_FAIL));
        }

        //记录操作日志
//        payLogService.insertLog(payDeal.getPayId(), payDeal.getPayPaymentNo(), payDeal.getTradeId(), PayStatus.CREATE_PAYMENT.getValue(), BusiConstant.OPERATE_SUCCESS, JSON.toJSONString(paymentRequest), JSON.toJSONString(respContent));

        return respContent;
    }

    /**
     * 调用第三方进行支付
     *
     * @param payDeal        支付平台记录
     * @param paymentRequest 下单请求参数
     * @return 请求返回参数
     */
    private String requestAllinChannel(PayDeal payDeal, PaymentRequest paymentRequest) {
        PayDeal payDealUpd = new PayDeal();
        payDealUpd.setPayId(payDeal.getPayId());
        //调用钱方支付
        Map<String, String> requestMap = new HashMap<>(5);
        requestMap.put("payPaymentNo", payDeal.getPayPaymentNo());
        requestMap.put("payAmount", payDeal.getRequestAmount().toString());
        requestMap.put("channelType", paymentRequest.getTrade_type());
        AllinpayResponse allinPayResponse = (AllinpayResponse) strategies.generatePayParams(BusinessConstant.ALLINPAY, requestMap);
        //根据第三方返回信息分别处理
        if (allinPayResponse != null && BusinessConstant.PAY_REQUEST_SUCCESS.equals(allinPayResponse.getCode())) {
            logger.info("调通联下单成功:" + payDeal.getPayId());
            //更新流水中的钱方订单号
            payDealUpd.setChannelTransaction(allinPayResponse.getTrxid());
            payDealUpd.setPayStatus(PayStatus.PAYING.getValue());

            if (payDealService.updatePayDeal(payDealUpd) > 0) {
                //插入task
                PayEventBus.post(new payTaskModel(payDeal));
                //返回参数处理
                return allinPayResponse.getMsg();

            } else {
                logger.error("下单后,更新支付流水失败:" + payDeal.getPayPaymentNo());
                throw new BusinessException(ExceptionStatus.E2003001.getCode(), ExceptionStatus.E2003001.getMessage());
            }
        } else {
            logger.error("通联下单失败:" + payDeal.getPayId());
            throw new BusinessException(ExceptionStatus.E2001005.getCode(), ExceptionStatus.E2001005.getMessage());
        }
    }

    /**
     * 调用第三方进行支付
     *
     * @param payDeal        支付平台记录
     * @param paymentRequest 下单请求参数
     * @return 请求返回参数
     */
    private AllinpayResponse requestAllinCodeChannel(PayDeal payDeal, PaymentRequest paymentRequest) {
        PayDeal payDealUpd = new PayDeal();
        payDealUpd.setPayId(payDeal.getPayId());

        Map<String, String> requestMap = new HashMap<>(5);
        requestMap.put("payPaymentNo", payDeal.getPayPaymentNo());
        requestMap.put("payAmount", payDeal.getRequestAmount().toString());
        requestMap.put("channelType", paymentRequest.getTrade_type());
        requestMap.put("authcode", paymentRequest.getAuthcode());
        AllinpayResponse allinPayResponse = (AllinpayResponse) strategies.generatePayParams(BusinessConstant.ALLINPAY, requestMap);

        //根据第三方返回信息分别处理
        if (allinPayResponse != null && BusinessConstant.PAY_REQUEST_SUCCESS.equals(allinPayResponse.getCode())) {
            logger.info("调通联支付成功:" + payDeal.getPayId());
            //更新流水中的通联订单号
            payDealUpd.setChannelTransaction(allinPayResponse.getTrxid());
            payDealUpd.setPayStatus(PayStatus.PAY_SUCCESS.getValue());

            if (payDealService.updatePayDeal(payDealUpd) > 0) {
                //插入task
//                PayEventBus.post(new payTaskModel(payDeal));
                //返回参数处理
                return allinPayResponse;
            } else {
                logger.error("下单后,更新支付流水失败:" + payDeal.getPayPaymentNo());
                return null;
            }
        } else {
            logger.error("通联支付中:" + payDeal.getPayId());
            //更新流水中的通联订单号
            payDealUpd.setChannelTransaction(allinPayResponse.getTrxid());
            payDealUpd.setPayStatus(PayStatus.PAYING.getValue());

            if (payDealService.updatePayDeal(payDealUpd) > 0) {
                //插入task
                PayEventBus.post(new payTaskModel(payDeal));
                //返回参数处理
                return allinPayResponse;

            } else {
                logger.error("下单后,更新支付流水失败:" + payDeal.getPayPaymentNo());
                return null;
            }
        }
    }

    public BaseResponse codePay(PaymentRequest paymentRequest) {

        //字段校验
        PayAssert.notNull(paymentRequest.getTrade_module(), ExceptionStatus.E1002002.getCode(), ExceptionStatus.E1002002.getMessage());

//        if (!paymentRequest.getPay_way().equals(PayWay.ANDROID.getName())) {
//            throw new BusinessException(ExceptionStatus.E1002002.getCode(), "payWay 字段错误");
//        }

        AllinResponse<AllinCodeContent> response = new AllinResponse<>();
        AllinCodeContent content = this.DealPayAllinCodeRequest(paymentRequest);
        response.setContent(content);
        if (content.getPayStatus() == 1) {
            response.setRet(Integer.parseInt(ExceptionStatus.SUCCESS.getCode()));
            response.setMsg(ExceptionStatus.SUCCESS.getMessage());
        } else {
            response.setRet(Integer.parseInt(ExceptionStatus.FAIL_S.getCode()));
            response.setMsg(ExceptionStatus.FAIL_S.getMessage());
        }

        return response;
    }


}
